#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <cmath>
using namespace std;
struct delta{
int n=0, m=0;
int** table;
map<char, int> alphaInd;
vector<char> Sigma;
delta(string T, string P){
this->n=P.length()+1;
for(int i=0; i<T.length(); ++i){
if(find(this->Sigma.begin(), this->Sigma.end(), T[i])==this->Sigma.end()){
this->Sigma.push_back(T[i]);
}
}
sort(Sigma.begin(), Sigma.end());
this->m=Sigma.size();
for(int i=0; i<this->m; ++i){
alphaInd[Sigma[i]]=i;
}
table=new int*[this->n];
for(int i=0; i<this->n; ++i) table[i]=new int[this->m];
}
int* address(int i, char chr){
int j=this->alphaInd.at(chr);
return &table[i][j];
}
};
bool suffix(string a, string b){
if(a.length()>b.length()) return false;
for(int i=b.length()-a.length(), j=0; i<b.length(); ++i, j++){
if(a[j]!=b[i]) return false;
}
return true;
}
void ComputeTransitionFunction(string P, delta& table){
int m=P.length();
for(int q=0; q<m+1; ++q){
for(char a: table.Sigma){
int k=min(m+1, q+2);
do{
k--;
}while(!suffix(P.substr(0, k), P.substr(0, q)+a));
*table.address(q, a)=k;
}
}
}
int FiniteAutomatonMatcher(string T, int m, delta& table){
int n=T.length();
int q=0;
for(int i=0; i<n; ++i){
q=(*table.address(q, T[i]));
if(q==m) return i-m+1;
}
return -1;
}
int main(void){
string T="abababacaba";
string P="ababaca";
delta table(T, P);
ComputeTransitionFunction(P, table);
for(int i=0; i<table.n; ++i){
for(int j=0; j<table.m; ++j) std::cout<<table.table[i][j]<<' ';
std::cout<<'\n';
}
std::cout<<std::endl;
int point=FiniteAutomatonMatcher(T, P.length(), table);
std::cout<<"Point: "<<point<<'\n';
for(int i=0; i<P.length(); ++i){
std::cout<<T[point+i]<<' ';
}
std::cout<<std::endl;
return 0;
}